package edu.hrbu.redis01.controller;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import edu.hrbu.redis01.entity.Goods;
import edu.hrbu.redis01.entity.User;
import edu.hrbu.redis01.service.GoodsService;
import edu.hrbu.redis01.service.UserService;
import edu.hrbu.redis01.util.R;
import edu.hrbu.redis01.vo.UserLoginVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;

import java.util.concurrent.TimeUnit;

/**
 * @author 徐登宇
 */
@RestController
@RequestMapping("/main")
public class MainController {

    public static final int INIT_GOODS_COUNT = 0;

    public static final int GOODS_SALE_COUNT = 10;

    // 单位都是秒
    public static final int CODE_KEY_TTL = 120;
    public static final int LOGIN_KEY_TTL = 1800;
    public static final int GOODS_SALE_TTL = 600;

    public static final String CODE_KEY = "code:key:";
    public static final String LOGIN_KEY = "login:key:";
    public static final String GOODS_KEY = "goods:key";

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private UserService userService;

    @Autowired
    private GoodsService goodsService;

    // 通过手机号获取验证码（有效时间2分钟）【有直接获取，没有先自动注册】
    @GetMapping("/code")
    public R code(@RequestParam("phone") String phone) {
        // 手机号为空
        if (ObjectUtils.isEmpty(phone)) {
            return R.fail("手机号不可为空");
        }
        if (phone.length() != 11) {
            return R.fail("手机号格式错误");
        }
        // 通过手机号判断是否有该用户
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getUserPhone, phone);

        User userDo = userService.getOne(wrapper);
        if (userDo == null) {
            // 不存在，就创建
            userDo = new User();
            userDo.setUserPhone(phone);
            userDo.setGoodsCount(INIT_GOODS_COUNT);
            userService.save(userDo);
        }

        String code = RandomUtil.randomNumbers(6);
        String codeKey = CODE_KEY + phone;
        // 验证码有效时间：30s
        stringRedisTemplate.opsForValue().set(codeKey, code, CODE_KEY_TTL, TimeUnit.SECONDS);
        return R.ok("code: " + code);

    }

    // 通过手机号+验证码登录
    @PostMapping("/login")
    public R login(@RequestBody UserLoginVo userLoginVo) {
        if (ObjectUtils.isEmpty(userLoginVo.getPhone()) || ObjectUtils.isEmpty(userLoginVo.getCode())) {
            // 用户登录信息为空
            return R.fail("登录数据不可为空");
        }
        String inputPhone = userLoginVo.getPhone();
        String inputCode = userLoginVo.getCode();
        String codeParam = stringRedisTemplate.opsForValue().get(CODE_KEY + inputPhone);
        if (ObjectUtils.isEmpty(codeParam) || !inputCode.equals(codeParam)) {
            // 手机号未获取到验证码 | 验证码输入的不正确
            return R.fail("验证码错误");
        }
        // 通过手机号获取用户信息
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getUserPhone, userLoginVo.getPhone());
        User userDo = userService.getOne(wrapper);
        // 将用户对象序列化为json
        String loginKey = LOGIN_KEY + userDo.getUserPhone();
        JSON userJson = JSONUtil.parse(userDo);
//        System.err.println("@@@" + userJson.toString());
        // 将用户信息存到redis中【有效时间：30分钟】
        stringRedisTemplate.opsForValue().set(loginKey, userJson.toString(), LOGIN_KEY_TTL, TimeUnit.SECONDS);
        return R.ok("loginkey: " + loginKey);

    }

    // 指定限时商品【10分钟】
    // 【数据库中不修改，等redis数据被减，再减数据库中的数据】
    @PostMapping("/upload1/{goodsId}")
    public R upload1(@PathVariable("goodsId") Long goodsId) {

        // 通过goodsId查询余量
        Goods goods = goodsService.getById(goodsId);
//        System.err.println("@@@: "+goods);
        if (goods.getGoodsCount() > GOODS_SALE_COUNT && !ObjectUtils.isEmpty(goods)) {
            String goodsKey = GOODS_KEY + goods.getGoodsId();
            // 如果数据库中存量大于要存入redis的量，就将该数据存到redis中
            stringRedisTemplate.opsForValue().set(goodsKey, Integer.toString(GOODS_SALE_COUNT), GOODS_SALE_TTL, TimeUnit.SECONDS);
            return R.ok("goodsKey: " + goodsKey);
        }
        return R.ok("存量不足");
    }

    // 限时抢
    @PostMapping("/sale/{userId}/{goodsId}")
    public R sale(@PathVariable("userId") Long userId,
                  @PathVariable("goodsId") Long goodsId,
                  @RequestParam("count") int count) {
        String loginKey = LOGIN_KEY + userId;
        // TODO 通过userId判断用户是否还在有效时间内

        // TODO 如果不在，返回错误信息

        // 否则，获取redis中商品的余量
        String goodsKey = GOODS_KEY + goodsId;
        String strGoodsCount = stringRedisTemplate.opsForValue().get(goodsKey);
        if (ObjectUtils.isEmpty(strGoodsCount)) {
            // 如果余量不足，返回错误信息
            return R.ok("商品已售空");
        }
        // 否则，比较用户的购买量和商品的余量做比较
        int goodsCount = Integer.parseInt(strGoodsCount);
        if (goodsCount < count) {
            // 不足，返回错误信息
            return R.ok("商品余量不足");
        }
        // 商品正好全卖完
        if (goodsCount == count) stringRedisTemplate.delete(goodsKey);
        // 否则，更新redis中商品的余量，并更新数据库对应数据
        Long goodsTTl = stringRedisTemplate.getExpire(goodsKey);
        if (ObjectUtils.isEmpty(goodsTTl)) {
            return R.ok("限时抢已截止");
        }
//        System.err.println("@@@@@"+goodsTTl);
        stringRedisTemplate.opsForValue().set(goodsKey, Integer.toString((goodsCount - count)), goodsTTl, TimeUnit.SECONDS);

        User user = userService.getById(userId);
        user.setGoodsCount(user.getGoodsCount() + count);
        userService.updateById(user);

        Goods goods = goodsService.getById(goodsId);
        goods.setGoodsCount(goods.getGoodsCount() - count);
        goodsService.updateById(goods);

        // 返回正确信息
        return R.ok();
    }

}
